using System;
using System.Collections.Generic;
using UnityEngine;

namespace Yoozoo.Gameplay.City
{
    public class CityRealAiConfigManager
    {
        public CityRealAiEventPointRoomConfig EmptyEventPointRoomCfg { get; private set; }
        
        public CityRealAiRoomEventConfig EmptyRoomEventCfg { get; private set; }
        
        public CityRealAiRoleInfoConfig EmptyRoleInfoCfg { get; private set; }
        
        public CityRealAiRoomBehaviorConfig EmptyRoomBehaviorCfg { get; private set; }
        
        public CityRealAiRoleConfig EmptyRoleCfg { get; private set; }
        
        public CityRealAiEventTreeConfig EmptyEventTreeCfg { get; private set; }
        
        public CityRealAiEventConfig EmptyEventCfg { get; private set; }
        
        public CityRealAiNPCBonePathConfig EmptyBonePathCfg { get; private set; }
        
        public CityRealAiOperateInteractiveConfig EmptyOperateInteractiveConfig { get; private set; }
        
        public CityRealAiSpecialConfig EmptySpecialConfig { get; private set; }
        
        public CityRealAiSpecialRecoverConfig EmptySpecialRecoverConfig { get; private set; }
        
        public Dictionary<int, CityRealAiEventPointRoomConfig> EventPointRoomDic { get; private set; }
        
        public Dictionary<int, Dictionary<int, CityRealAiRoomEventConfig>> RoomEventConfigDic { get; private set; }
        
        public Dictionary<int, CityRealAiRoleInfoConfig> RoleInfoConfigDic { get; private set; }
        
        public Dictionary<int, List<CityRealAiRoomBehaviorConfig>> RoomBehaviorConfigDic { get; private set; }

        public Dictionary<int, CityRealAiRoleConfig> RoleConfigDic { get; private set; }
        
        public Dictionary<int, CityRealAiEventTreeConfig> EventTreeConfigDic { get; private set; }
        
        public Dictionary<int, CityRealAiEventConfig> EventConfigDic { get; private set; }
        
        public Dictionary<int, CityRealAiNPCBonePathConfig> BonePathConfigDic { get; private set; }

        public List<CityRealAiNPCQueueMoodConfig> QueueMoodConfigs { get; private set; }
        
        public Dictionary<int, CityRealAiOperateInteractiveConfig> InteractiveConfigs { get; private set; }
        
        public Dictionary<int, CityRealAiSpecialConfig> SpecialConfigs { get; private set; }
        
        public Dictionary<int, CityRealAiSpecialRecoverConfig> SpecialRecoverConfigs { get; private set; }

        public Dictionary<int, CityRealAiGoodsConfig> VirtualGoodsConfigDic { get; private set; }

        private Dictionary<int, float> RoomReceptionTimeDic;
        
        public GlobalVariablesConfig GlobalCfg { get; private set; }

        public void OnInitialize()
        {
            EmptyEventPointRoomCfg = new CityRealAiEventPointRoomConfig()
            {
                roomId = -1,
                birthPointPosList = Array.Empty<Vector3>(),
                goodsList = Array.Empty<CityRealAiGoodsConfig>(),
                MovePointList = Array.Empty<Vector3>(),
                WaitPointPosList = Array.Empty<Vector3>(),
                WaitPointRotList = Array.Empty<Vector3>(),
            };
            EmptyRoomEventCfg = new CityRealAiRoomEventConfig()
            {
                room_id = -1,
                link_npc = Array.Empty<Vector3>(),
                ex_event_tree = Array.Empty<Vector2>(),
            };
            EmptyRoleInfoCfg = new CityRealAiRoleInfoConfig()
            {
                role_id = -1,
            };
            EmptyRoomBehaviorCfg = new CityRealAiRoomBehaviorConfig()
            {
                room_id = -1,
                default_npc_array = Array.Empty<int>(),
                role_type_array = Array.Empty<int>(),
            };
            EmptyRoleCfg = new CityRealAiRoleConfig()
            {
                role_type = -1,
                event_tree_array = Array.Empty<Vector2>(),
                bubble_event_array = Array.Empty<Vector3>(),
                bubble_weight = Array.Empty<int>(),
                bubble_type = Array.Empty<Vector2>(),
                condition_event_array = Array.Empty<Vector3>(),
                condition_weight = Array.Empty<int>(),
                condition_type = Array.Empty<Vector2>(),
                interactive_name_array = Array.Empty<string>(),
                interactive_event_array = Array.Empty<Vector2>(),
                interactive_weight = Array.Empty<int>(),
                interactive_type = Array.Empty<Vector2>(),
                break_event_array = Array.Empty<Vector3>(),
                break_weight = Array.Empty<int>(),
                break_type = Array.Empty<Vector2>(),
                repower_event_tree_array = Array.Empty<Vector3>(),
                idle_event_tree_array = Array.Empty<Vector2>(),
                guarant_event_tree_array = Array.Empty<Vector2>(),
                waite_tree_array = Array.Empty<Vector2>(),
                cost_tree_array = Array.Empty<Vector2>(),
                unlock_area_array = Array.Empty<Vector2>(),
                employ_front_array = Array.Empty<Vector2>(),
                faulttolerance_tree_array = Array.Empty<Vector2>(),
            };
            EmptyEventTreeCfg = new CityRealAiEventTreeConfig()
            {
                event_tree_id = -1,
                condition = Array.Empty<Vector2>(),
                event_array = Array.Empty<Vector3>(),
            };
            EmptyEventCfg = new CityRealAiEventConfig()
            {
                event_id = -1,
                condition = Array.Empty<Vector2>(),
                demand = Array.Empty<Vector2>(),
            };
            EmptyBonePathCfg = new CityRealAiNPCBonePathConfig()
            {
                id = -1,
            };
            EmptyOperateInteractiveConfig = new CityRealAiOperateInteractiveConfig()
            {
                id = -1,
            };
            EmptySpecialConfig = new CityRealAiSpecialConfig()
            {
                id = -1,
            };
            EmptySpecialRecoverConfig = new CityRealAiSpecialRecoverConfig()
            {
                id = -1,
            };

            EventPointRoomDic = new Dictionary<int, CityRealAiEventPointRoomConfig>();
            RoomEventConfigDic = new Dictionary<int, Dictionary<int, CityRealAiRoomEventConfig>>();
            RoleInfoConfigDic = new Dictionary<int, CityRealAiRoleInfoConfig>();
            RoomBehaviorConfigDic = new Dictionary<int, List<CityRealAiRoomBehaviorConfig>>();
            RoleConfigDic = new Dictionary<int, CityRealAiRoleConfig>();
            EventTreeConfigDic = new Dictionary<int, CityRealAiEventTreeConfig>();
            EventConfigDic = new Dictionary<int, CityRealAiEventConfig>();
            BonePathConfigDic = new Dictionary<int, CityRealAiNPCBonePathConfig>();
            QueueMoodConfigs = new List<CityRealAiNPCQueueMoodConfig>();
            VirtualGoodsConfigDic = new Dictionary<int, CityRealAiGoodsConfig>();
            RoomReceptionTimeDic = new Dictionary<int, float>();
            InteractiveConfigs = new Dictionary<int, CityRealAiOperateInteractiveConfig>();
            SpecialConfigs = new Dictionary<int, CityRealAiSpecialConfig>();
            SpecialRecoverConfigs = new Dictionary<int, CityRealAiSpecialRecoverConfig>();
        }

        public void SetupEventPointRoomConfig(ref CityRealAiEventPointRoomConfigs eventPointRoomConfigs)
        {
            for (int i = 0; i < eventPointRoomConfigs.array.Length; i++)
            {
                EventPointRoomDic.Add(eventPointRoomConfigs.array[i].roomId, eventPointRoomConfigs.array[i]);
            }
        }
        
        public void SetupRoomEventConfig(ref CityRealAiRoomEventConfigs roomEventConfigs)
        {
            for (int i = 0; i < roomEventConfigs.array.Length; i++)
            {
                if (!RoomEventConfigDic.TryGetValue(roomEventConfigs.array[i].room_id, out var roomDic))
                {
                    roomDic = new Dictionary<int, CityRealAiRoomEventConfig>();
                    RoomEventConfigDic.Add(roomEventConfigs.array[i].room_id, roomDic);
                }
                roomDic.Add(roomEventConfigs.array[i].room_state, roomEventConfigs.array[i]);
            }
        }
        
        public void SetupRoleInfoConfig(ref CityRealAiRoleInfoConfigs roleInfoConfigs)
        {
            for (int i = 0; i < roleInfoConfigs.array.Length; i++)
            {
                RoleInfoConfigDic.Add(roleInfoConfigs.array[i].role_id, roleInfoConfigs.array[i]);
            }
        }
        
        public void SetupRoomBehaviorConfig(ref CityRealAiRoomBehaviorConfigs behaviorConfigs)
        {
            for (int i = 0; i < behaviorConfigs.array.Length; i++)
            {
                if (!RoomBehaviorConfigDic.TryGetValue(behaviorConfigs.array[i].room_id, out var roomBehaviorDic))
                {
                    roomBehaviorDic = new List<CityRealAiRoomBehaviorConfig>();
                    RoomBehaviorConfigDic.Add(behaviorConfigs.array[i].room_id, roomBehaviorDic);
                }
                roomBehaviorDic.Add(behaviorConfigs.array[i]);
            }
        }

        public void SetupRoleConfig(ref CityRealAiRoleConfigs roleConfigs)
        {
            for (int i = 0; i < roleConfigs.array.Length; i++)
            {
                RoleConfigDic.Add(roleConfigs.array[i].role_type, roleConfigs.array[i]);
            }
        }

        public void SetupEventTreeConfig(ref CityRealAiEventTreeConfigs eventTreeConfigs)
        {
            for (int i = 0; i < eventTreeConfigs.array.Length; i++)
            {
                EventTreeConfigDic.Add(eventTreeConfigs.array[i].event_tree_id, eventTreeConfigs.array[i]);
            }
        }

        public void SetupEventConfig(ref CityRealAiEventConfigs eventConfigs)
        {
            for (int i = 0; i < eventConfigs.array.Length; i++)
            {
                if(EventConfigDic.ContainsKey(eventConfigs.array[i].event_id))
                {
                    Debug.LogError("EventConfigDic has same key: " + eventConfigs.array[i].event_id);
                }
                EventConfigDic[eventConfigs.array[i].event_id] = eventConfigs.array[i];
            }
        }

        public void SetupBonePathConfig(ref CityRealAiNPCBonePathConfigs bonePathConfigs)
        {
            for (int i = 0; i < bonePathConfigs.array.Length; i++)
            {
                BonePathConfigDic.Add(bonePathConfigs.array[i].id,  bonePathConfigs.array[i]);
            }
        }

        public void SetupQueueMoodConfig(ref CityRealAiNPCQueueMoodConfigs queueMoodConfigs)
        {
            for (int i = 0; i < queueMoodConfigs.array.Length; i++)
            {
                QueueMoodConfigs.Add(queueMoodConfigs.array[i]);
            }
        }
        
        public void SetupOperateInteractiveConfig(ref CityRealAiOperateInteractiveConfigs operateInteractiveConfigs)
        {
            for (int i = 0; i < operateInteractiveConfigs.array.Length; i++)
            {
                InteractiveConfigs.Add(operateInteractiveConfigs.array[i].id, operateInteractiveConfigs.array[i]);
            }
        }

        public void SetupSpecialConfigs(ref CityRealAiSpecialConfigs specialConfigs)
        {
            for (int i = 0; i < specialConfigs.array.Length; i++)
            {
                SpecialConfigs.Add(specialConfigs.array[i].id, specialConfigs.array[i]);
            }
        }

        public void SetupSpecialRecoverConfigs(ref CityRealAiSpecialRecoverConfigs specialRecoverConfigs)
        {
            for (int i = 0; i < specialRecoverConfigs.array.Length; i++)
            {
                SpecialRecoverConfigs.Add(specialRecoverConfigs.array[i].id, specialRecoverConfigs.array[i]);
            }
        }

        public void SetupGlobalVariablesConfig(ref GlobalVariablesConfig globalConfig)
        {
            GlobalCfg = globalConfig;
        }

        public CityRealAiEventPointRoomConfig GetEventPointRoomCfg(int roomId)
        {
            if (EventPointRoomDic.TryGetValue(roomId, out var roomConfig))
            {
                return roomConfig;
            }

            return EmptyEventPointRoomCfg;
        }

        public Dictionary<int, CityRealAiRoomEventConfig> GetRoomEventConfigs(int roomId)
        {
            if (RoomEventConfigDic.TryGetValue(roomId, out var roomEventConfigs))
            {
                return roomEventConfigs;
            }

            return null;
        }

        public CityRealAiRoleInfoConfig GetAiRoleInfoConfig(int roleId)
        {
            if (RoleInfoConfigDic.TryGetValue(roleId, out var roleInfoConfig))
            {
                return roleInfoConfig;
            }

            return EmptyRoleInfoCfg;
        }

        public CityRealAiRoomBehaviorConfig GetRoleTypeByRoomBehaviorConfig(int roomId, int level, ref List<CityRealAiNpcInfo> roleInfoList)
        {
            if (RoomBehaviorConfigDic.TryGetValue(roomId, out var roomBehaviorList))
            {
                List<int> tempRoleIdList = null;
                for (int i = roomBehaviorList.Count - 1; i >= 0; i--)
                {
                    var behavior = roomBehaviorList[i];
                    if (behavior.default_npc_array.Length == roleInfoList.Count)
                    {
                        // 对比两个数组是否含有相同的数据（不要求顺序）
                        if (tempRoleIdList == null)
                        {
                            tempRoleIdList = new List<int>();
                        }
                        tempRoleIdList.Clear();
                        
                        for (int j = 0; j < roleInfoList.Count; j++)
                        {
                            tempRoleIdList.Add(roleInfoList[j].cityRoleId);
                        }

                        for (int j = 0; j < behavior.default_npc_array.Length; j++)
                        {
                            var roleId = behavior.default_npc_array[j];
                            if (!tempRoleIdList.Remove(roleId)) // remove失败，跟当前不同
                            {
                                break;
                            }
                        }

                        if (tempRoleIdList.Count == 0)
                        {
                            // 给roleInfoList 排序，让roleInfoList和default_npc_array顺序保持一致。
                            for (int j = 0; j < roleInfoList.Count; j++)
                            {
                                var roleId = behavior.default_npc_array[j];
                                if (roleId == roleInfoList[j].cityRoleId)
                                {
                                    continue;
                                }

                                var tempIndex = roleInfoList.FindIndex(j + 1, roleInfo => roleInfo.cityRoleId == roleId);
                                (roleInfoList[tempIndex], roleInfoList[j]) = (roleInfoList[j], roleInfoList[tempIndex]);
                            }
                            
                            return behavior;
                        }
                    }
                }
            }

            return EmptyRoomBehaviorCfg;
        }

        public CityRealAiRoleConfig GetAiRoleConfig(int roleId)
        {
            if (RoleConfigDic.TryGetValue(roleId, out var roleConfig))
            {
                return roleConfig;
            }

            return EmptyRoleCfg;
        }
        
        public CityRealAiEventTreeConfig GetAiEventTreeConfig(int treeId)
        {
            if (EventTreeConfigDic.TryGetValue(treeId, out var eventTreeConfig))
            {
                return eventTreeConfig;
            }

            return EmptyEventTreeCfg;
        }
        
        public CityRealAiEventConfig GetAiEventConfig(int eventId)
        {
            if (EventConfigDic.TryGetValue(eventId, out var eventConfig))
            {
                return eventConfig;
            }

            return EmptyEventCfg;
        }

        public CityRealAiNPCBonePathConfig GetBonePathConfig(int pathId)
        {
            if (BonePathConfigDic.TryGetValue(pathId, out var bonePathConfig))
            {
                return bonePathConfig;
            }

            return EmptyBonePathCfg;
        }

        public CityRealAiOperateInteractiveConfig GetOperateInteractiveConfig(int operateInterativeId)
        {
            if (InteractiveConfigs.TryGetValue(operateInterativeId, out var config))
            {
                return config;
            }

            return EmptyOperateInteractiveConfig;
        }

        public CityRealAiSpecialConfig GetSpecialConfig(int specialId)
        {
            if (SpecialConfigs.TryGetValue(specialId, out var specialCfg))
            {
                return specialCfg;
            }

            return EmptySpecialConfig;
        }

        public CityRealAiSpecialRecoverConfig GetSpecialRecoverConfig(int specialId)
        {
            if (SpecialRecoverConfigs.TryGetValue(specialId, out var specialRecoverConfig))
            {
                return specialRecoverConfig;
            }

            return EmptySpecialRecoverConfig;
        }

        public void SetRoomReceptionTime(int buildingId, float time)
        {
            // 特殊记录下检票时长
            if (buildingId == CityRealAiConst.WallId)
            {
                CityRealAiConst.CheckTicketTime = time;
            }
            
            RoomReceptionTimeDic[buildingId] = time;
        }

        public float GetRoomReceptionTime(int buildingId)
        {
            if (RoomReceptionTimeDic.TryGetValue(buildingId, out var time))
            {
                return time;
            }

            return CityRealAiConst.DefaultRoomReceptionTime;
        }

        public void Dispose()
        {
            if (RoomEventConfigDic != null)
            {
                RoomEventConfigDic.Clear();
                RoomEventConfigDic = null;
            }

            if (RoleInfoConfigDic != null)
            {
                RoleInfoConfigDic.Clear();
                RoleInfoConfigDic = null;
            }

            if (RoomBehaviorConfigDic != null)
            {
                RoomBehaviorConfigDic.Clear();
                RoomBehaviorConfigDic = null;
            }

            if (RoleConfigDic != null)
            {
                RoleConfigDic.Clear();
                RoleConfigDic = null;
            }

            if (EventTreeConfigDic != null)
            {
                EventTreeConfigDic.Clear();
                EventTreeConfigDic = null;
            }

            if (EventConfigDic != null)
            {
                EventConfigDic.Clear();
                EventConfigDic = null;
            }

            if (BonePathConfigDic != null)
            {
                BonePathConfigDic.Clear();
                BonePathConfigDic = null;
            }

            if (VirtualGoodsConfigDic != null)
            {
                VirtualGoodsConfigDic.Clear();
                VirtualGoodsConfigDic = null;
            }

            if (RoomReceptionTimeDic != null)
            {
                RoomReceptionTimeDic.Clear();
                RoomReceptionTimeDic = null;
            }

            if (InteractiveConfigs != null)
            {
                InteractiveConfigs.Clear();
                InteractiveConfigs = null;
            }
        }
    }
}